#include "StdAfx.h"
#include ".\shotcut.h"

float computeEntropy(IplImage * img) {
	float hist[256];
	memset(hist, 0, sizeof(float) * 256);
	int i, j, val;
	uchar *uch;
	float ratio = 1.0 / img->width / (float)(img->height);

	for (j = 0; j < img->height; j++) {
		uch = cvPtr2D(img, j, 0);
		for (i = 0; i < img->width; i++) {
			val = (int)(*uch);
			hist[val]++;
			uch++;
		}
	}

	float fix = 0.0001 * log(0.0001);
	float sum = 0;
	for (i = 0; i < 256; i++) {
		if (hist[i] == 0) {
			sum -= fix;
			continue;
		}
		hist[i] *= ratio;
		sum -= hist[i] * log((double)hist[i]);
	}

	return sum;
}

CShotCut::CShotCut(void)
{
	m_init_t = true;
	m_lev = 16;
	m_f_count = 0;
	//m_thres = 0.9;//0.4;
	m_thres = 0.85;// for shot cut

	memset(m_hsv_hist, 0, sizeof(float) * 3 * m_lev);
}

CShotCut::~CShotCut(void)
{
}

void CShotCut::setThres(float thres) {
	m_thres = thres;
}

bool CShotCut::checkCut(IplImage * img)
{
	if (img->depth != 8)
		return false;
	
	CvSize size;
	size.width = 80;
	size.height = 60;
	IplImage * src_img = cvCreateImage(size, 8, 3);
	IplImage * hsv_img = cvCreateImage(size, 8, 3);
	cvResize(img, src_img, CV_INTER_LINEAR);
	cvCvtColor(src_img, hsv_img, CV_RGB2HSV);

	uchar * uch;
	
	int i, j;
	float cur_fea[48];
	memset(cur_fea, 0, sizeof(float) * 3 * m_lev);
	int val;
	int inter = 256 / m_lev, ind;
	float tmp;
	for (j = 0; j < size.height; j++) {
		uch = cvPtr2D(hsv_img, j, 0);
		for (i = 0; i < size.width; i++) {
			val = (int)(*uch);
			ind = val / inter;
			tmp = cur_fea[ind];
			cur_fea[ind] = tmp + 1;
			uch++;

			val = (int)(*uch);
			ind = val / inter + 16;
			tmp = cur_fea[ind];
			cur_fea[ind] = tmp + 1;
			uch++;

			val = (int)(*uch);
			ind = val / inter + 32;
			tmp = cur_fea[ind];
			cur_fea[ind] = tmp + 1;
			uch++;
		}
	}
	tmp = 1.0 / size.width / size.height / 3.0;
	for (j = 0; j < 48; j++) {
		cur_fea[j] = cur_fea[j] * tmp;
	}
	cvReleaseImage(&src_img);
	cvReleaseImage(&hsv_img);

	if (m_init_t) {
		for (j = 0; j < 48; j++) {
			m_hsv_hist[j] = cur_fea[j];
		}
		m_f_count = 1;
		m_init_t = false;
		return false;
	} 
	
	float sim = computeSim(m_hsv_hist, cur_fea, 48);
	if (sim < m_thres) {
		for (j = 0; j < 48; j++) {
			m_hsv_hist[j] = cur_fea[j];
		}
		m_f_count = 1;
		return true;
	}

	m_f_count++;
	for (j = 0; j < 48; j++) {
		m_hsv_hist[j] += (cur_fea[j] - m_hsv_hist[j]) / m_f_count;
	}
	return false;
}

float CShotCut::computeSim(float * d1, float * d2, int size)
{
	float *p, *q;
	p = d1;
	q = d2;
	float sum = 0;
	for (int i = 0; i < size; i++) {
		float tmp;
		tmp = ((*p) > (*q)) ? (*q) : (*p);
		sum +=tmp;
		p++;
		q++;
	}
	return sum;
}

bool CShotCut::checkCut(IplImage * img, float &outputSim) {
	if (img->depth != 8)
		return false;
	
	int size_thres = 100;
	int curMaxSize = (img->width < img->height) ? img->height : img->width;
	float ratio = (float)size_thres / (float)curMaxSize;
	CvSize size;
	size.width = img->width * ratio;
	size.height = img->height * ratio;
	//size.width = 80;
	//size.height = 60;

	IplImage * src_img = cvCreateImage(size, 8, 3);
	IplImage * hsv_img = cvCreateImage(size, 8, 3);
	cvResize(img, src_img, CV_INTER_LINEAR);
	//cvCvtColor(src_img, hsv_img, CV_RGB2HSV);
	cvCvtColor(src_img, hsv_img, CV_BGR2Lab);
	
	uchar * uch;
	
	int i, j;
	float cur_fea[48];
	memset(cur_fea, 0, sizeof(float) * 3 * m_lev);
	int val;
	int inter = 256 / m_lev, ind;
	float tmp;
	for (j = 0; j < size.height; j++) {
		uch = cvPtr2D(hsv_img, j, 0);
		for (i = 0; i < size.width; i++) {
			val = (int)(*uch);
			ind = val / inter;
			tmp = cur_fea[ind];
			cur_fea[ind] = tmp + 1;
			uch++;

			val = (int)(*uch);
			ind = val / inter + 16;
			tmp = cur_fea[ind];
			cur_fea[ind] = tmp + 1;
			uch++;

			val = (int)(*uch);
			ind = val / inter + 32;
			tmp = cur_fea[ind];
			cur_fea[ind] = tmp + 1;
			uch++;
		}
	}
	tmp = 1.0 / size.width / size.height / 3.0;
	for (j = 0; j < 48; j++) {
		cur_fea[j] = cur_fea[j] * tmp;
	}
	cvReleaseImage(&src_img);
	cvReleaseImage(&hsv_img);

	if (m_init_t) {
		for (j = 0; j < 48; j++) {
			m_hsv_hist[j] = cur_fea[j];
		}
		m_f_count = 1;
		m_init_t = false;
		outputSim = 1.0;
		return false;
	} 
	
	float sim = computeSim(m_hsv_hist, cur_fea, 48);
	outputSim = sim;

	if (sim < m_thres) {
		for (j = 0; j < 48; j++) {
			m_hsv_hist[j] = cur_fea[j];
		}
		m_f_count = 1;
		return true;
	}

	m_f_count++;
	for (j = 0; j < 48; j++) {
		m_hsv_hist[j] += (cur_fea[j] - m_hsv_hist[j]) / m_f_count;
	}
	return false;
}
